// ByteUtil.ets
import util from '@ohos.util';

export class ByteUtil {
  private static readonly HEXES: string[] = [
    '0', '1', '2', '3',
    '4', '5', '6', '7',
    '8', '9', 'A', 'B',
    'C', 'D', 'E', 'F'
  ];

  /**
   * 字节数组转换成对应的16进制表示的字符串
   * @param src 字节数组
   * @returns 16进制字符串
   */
  static bytes2HexStrs(src: number[]): string {
    if (!src || src.length <= 0) {
      return "";
    }
    let builder = "";
    for (let i = 0; i < src.length; i++) {
      const v = src[i] & 0xFF;
      builder += this.HEXES[v >>> 4];
      builder += this.HEXES[v & 0x0F];
    }
    return builder.toUpperCase();
  }

  /**
   * 16进制字符串转换为字符串(UTF-8)
   * @param hexString 16进制字符串
   * @returns 解码后的字符串
   */
  static fromHexString(hexString: string): string {
    let result = "";
    hexString = hexString.toUpperCase();
    const hexDigital = "0123456789ABCDEF";
    const hexs = hexString.split('');
    const bytes = new Array<number>(hexString.length / 2);

    for (let i = 0; i < bytes.length; i++) {
      const n = hexDigital.indexOf(hexs[2 * i]) * 16 + hexDigital.indexOf(hexs[2 * i + 1]);
      bytes[i] = n & 0xFF;
    }

    // 在OpenHarmony中，可以使用TextDecoder来解码字节数组
    const decoder = new util.TextDecoder("utf-8");
    result = decoder.decodeWithStream(new Uint8Array(bytes));
    return result;
  }

  /**
   * 获取16进制字符串
   * @param num 数字
   * @returns 16进制字符串
   */
  static getHexInt(num: number): string {
    let hex = num.toString(16);
    if (hex.length === 1) {
      hex = "0" + hex.toUpperCase();
    } else {
      hex = hex.toUpperCase();
    }
    return hex;
  }

  /**
   * 十六进制字节数组转字符串
   * @param src 目标数组
   * @param dec 起始位置
   * @param length 长度
   * @returns 16进制字符串
   */
  static bytes2HexStr(src: number[], dec: number, length: number): string {
    const temp = src.slice(dec, dec + length);
    return this.bytes2HexStrs(temp);
  }

  /**
   * 16进制字符串转10进制数字
   * @param hex 16进制字符串
   * @returns 10进制数字
   */
  static hexStr2decimal(hex: string): number {
    return parseInt(hex, 16);
  }

  /**
   * 把十进制数字转换成足位的十六进制字符串,并补全空位
   * @param num 数字
   * @returns 16进制字符串
   */
  static decimal2fitHex(num: number): string {
    let hex = num.toString(16).toUpperCase();
    if (hex.length % 2 !== 0) {
      hex = "0" + hex;
    }
    return hex;
  }

  /**
   * 把十进制数字转换成足位的十六进制字符串,并补全空位
   * @param num 数字
   * @param strLength 字符串长度
   * @returns 16进制字符串
   */
  static decimal2fitHexs(num: number, strLength: number): string {
    let hexStr = this.decimal2fitHex(num);
    while (hexStr.length < strLength) {
      hexStr = "0" + hexStr;
    }
    return hexStr;
  }

  static fitDecimalStr(dicimal: number, strLength: number): string {
    let builder = dicimal.toString();
    while (builder.length < strLength) {
      builder = "0" + builder;
    }
    return builder;
  }

  /**
   * 字符串转十六进制字符串(UTF-8)
   * @param str 字符串
   * @returns 16进制字符串
   */
  static str2HexString(str: string): string {
    const chars = "0123456789ABCDEF".split('');
    let sb = "";
    const encoder = new util.TextEncoder();
    const bs = encoder.encode(str);

    for (let i = 0; i < bs.length; i++) {
      const bit = (bs[i] & 0xF0) >> 4;
      sb += chars[bit];
      sb += chars[bs[i] & 0x0F];
    }
    return sb;
  }

  /**
   * 字符串转十六进制字符串(GBK)
   * @param str 字符串
   * @returns 16进制字符串
   */
  static str2HexGBKString(str: string): string {
    // OpenHarmony目前不支持GBK编码，需要额外处理
    // 这里暂时使用UTF-8代替，实际使用时需要根据GBK编码表实现
    return this.str2HexString(str);
  }

  /**
   * 字符串转十六进制字符串(ASCII)
   * @param str 字符串
   * @returns 16进制字符串
   */
  static str2HexASCIIString(str: string): string {
    const chars = "0123456789ABCDEF".split('');
    let sb = "";
    const bs = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++) {
      bs[i] = str.charCodeAt(i) & 0xFF;
    }

    for (let i = 0; i < bs.length; i++) {
      const bit = (bs[i] & 0xF0) >> 4;
      sb += chars[bit];
      sb += chars[bs[i] & 0x0F];
    }
    return sb;
  }

  static byteToStringArray(bytes: number[]): string[] {
    const hexArray: string[] = [];
    for (let i = 0; i < bytes.length; i++) {
      const hex = this.HEXES[(bytes[i] >> 4) & 0x0F] + this.HEXES[bytes[i] & 0x0F];
      hexArray.push(hex);
    }
    return hexArray;
  }

  /**
   * 把16进制字符串转换成字节数组
   * @param hex 16进制字符串
   * @returns 字节数组
   */
  static hexStringToByte(hex: string): number[] {
    const len = hex.length / 2;
    const result = new Array<number>(len);
    const achar = hex.split('');

    for (let i = 0; i < len; i++) {
      const pos = i * 2;
      result[i] = (this.toByte(achar[pos]) << 4) | this.toByte(achar[pos + 1]);
    }
    return result;
  }

  private static toByte(c: string): number {
    return "0123456789ABCDEF".indexOf(c);
  }

  /**
   * 把十六进制表示的字节数组字符串，转换成十六进制字节数组
   * @param hex 16进制字符串
   * @returns 字节数组
   */
  static hexStr2bytes(hex: string): number[] {
    const len = hex.length / 2;
    const result = new Array<number>(len);
    const achar = hex.toUpperCase().split('');

    for (let i = 0; i < len; i++) {
      const pos = i * 2;
      result[i] = (this.hexChar2byte(achar[pos]) << 4) | this.hexChar2byte(achar[pos + 1]);
    }
    return result;
  }

  private static hexChar2byte(c: string): number {
    switch (c) {
      case '0': return 0;
      case '1': return 1;
      case '2': return 2;
      case '3': return 3;
      case '4': return 4;
      case '5': return 5;
      case '6': return 6;
      case '7': return 7;
      case '8': return 8;
      case '9': return 9;
      case 'A': return 10;
      case 'B': return 11;
      case 'C': return 12;
      case 'D': return 13;
      case 'E': return 14;
      case 'F': return 15;
      default: return -1;
    }
  }

  /**
   * 固定列时间乘
   * @param str 字符串
   * @returns 16进制字符串
   */
  static getReadTime(str: string): string {
    let hex = "0";
    if (str && str.length > 0) {
      hex = (parseInt(str) * 10).toString(16);
    }
    return hex;
  }

  /**
   * 字符串转hex
   * @param str 字符串
   * @returns 16进制字符串
   */
  static getHex(str: string): string {
    const arr = this.getHexStr1(str);
    return arr.join("");
  }

  /**
   * 获取16进制字符串
   * @param str 字符串
   * @returns 16进制字符串数组
   */
  static getHexStr1(str: string): string[] {
    let hex = "0";
    if (str && str.length > 0) {
      hex = parseInt(str).toString(16);
    }
    if (hex.length === 1) {
      hex = "0" + hex.toUpperCase();
    } else {
      hex = hex.toUpperCase();
    }
    return this.get2Hex(hex);
  }

  /**
   * 获取16进制字符串
   * @param num 数字
   * @returns 16进制字符串数组
   */
  static getHexStr(num: number): string[] {
    let hex = num.toString(16);
    if (hex.length === 1) {
      hex = "0" + hex.toUpperCase();
    } else {
      hex = hex.toUpperCase();
    }
    return this.get2Hex(hex);
  }

  /**
   * 获取16进制字符串
   * @param str 字符串
   * @returns 16进制字符串数组
   */
  static getHexStrFromString(str: string): string[] {
    let hex = "0";
    if (str && str.length > 0) {
      hex = parseInt(str).toString(16);
    }
    if (hex.length === 1) {
      hex = "000" + hex.toUpperCase();
    } else if (hex.length === 2) {
      hex = "00" + hex.toUpperCase();
    } else if (hex.length === 3) {
      hex = "0" + hex.toUpperCase();
    } else {
      hex = hex.toUpperCase();
    }
    return this.get2Hex(hex);
  }

  /**
   * 获取16进制字符串
   * @param str 字符串
   * @returns 16进制字符串数组
   */
  static getFloatHexStr(str: string): string[] {
    let hex = "0";
    if (str && str.length > 0) {
      hex = Math.floor(parseFloat(str)).toString(16);
    }
    if (hex.length === 1) {
      hex = "000" + hex.toUpperCase();
    } else if (hex.length === 2) {
      hex = "00" + hex.toUpperCase();
    } else if (hex.length === 3) {
      hex = "0" + hex.toUpperCase();
    } else {
      hex = hex.toUpperCase();
    }
    return this.get2Hex(hex);
  }

  static get2Hex(hex: string): string[] {
    const hexSD = new Array<string>(2);
    hexSD[0] = hex.substring(0, 2);
    hexSD[1] = hex.substring(2);
    return hexSD;
  }

  /**
   * 拼接数组
   * @param byteList 字节数组列表
   * @returns 合并后的字节数组
   */
  static byteMerger(...byteList: string[][]): string[] {
    let lengthByte = 0;
    for (let i = 0; i < byteList.length; i++) {
      lengthByte += byteList[i].length;
    }
    const allByte = new Array<string>(lengthByte);
    let countLength = 0;
    for (let i = 0; i < byteList.length; i++) {
      const b = byteList[i];
      for (let j = 0; j < b.length; j++) {
        allByte[countLength++] = b[j];
      }
    }
    return allByte;
  }

  /**
   * 16进制转浮点型
   * @param data 16进制字符串
   * @returns 浮点数
   */
  static getFloat(data: string): number {
    const b = parseInt(data, 16);
    return b / 10.0;
  }
}